package com.woniuxy.shiro.utils;

import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {


    //禁用session，保证每次都要重新认证，除非调用getsession
    @Bean
    protected SessionStorageEvaluator sessionStorageEvaluator() {
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }

    //配置安全管理器，传入自定义域，参数为域
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm myRealm){
        //使用默认的web管理器
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm);
        //将自定义的域交给manager统一管理
        defaultWebSecurityManager.setRealm(myRealm);
        return defaultWebSecurityManager;
    }

    //Filter工厂，设置对应的过滤条件和跳转条件，需要配置过滤所有请求
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean getFilterFactoryBean(DefaultWebSecurityManager securityManager){
        //1、创建shiro过滤器工厂
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        //2、设置安全管理器
        filterFactoryBean.setSecurityManager(securityManager);
        //3.通用配置,如果没有前后端分离配置这个（配置登录页面，登录成功页面，验证未成功页面）
//        filterFactory.setLoginUrl("/autherror?code=1"); //设置登录页面
//        filterFactory.setUnauthorizedUrl("/autherror?code=2"); //授权失败跳转页面
        //4.配置过滤器集合
        /*
         * key ：访问连接
         * 支持通配符的形式
         * value：过滤器类型
         * shiro常用过滤器类型
         * anno ：匿名访问（表明此链接所有人可以访问）
         * authc ：认证后访问（表明此链接需登录认证成功之后可以访问）
         */
//        Map<String,String> filterMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
//        filterMap.put("/user/home", "anon");
//        filterMap.put("/login", "anon");
//        filterMap.put("/user/**", "authc");
        //5、设置自定义jwt过滤器
        Map<String, Filter> jwt = new HashMap<>();
        jwt.put("jwt",new JWTFilter());
        filterFactoryBean.setFilters(jwt);
        /*
        6、设置所有请求都经过JWTFilter
        自定义url规则
        http://shiro.apache.org/web.html#urls-
        */
        Map<String, String> filterRuleMap = new HashMap<>();
        //所有请求都经过
        filterRuleMap.put("/**","anon");//暂时关闭
        //访问401和404不经过jwt
        filterRuleMap.put("/401","anon");
        filterRuleMap.put("/login","anon");
        filterFactoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return filterFactoryBean;
    }

    //开启shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new
                AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    //管理Subject主体对象,生命周期的组件,用户只是打印下生产销毁日志,请参考spring中bean的生命周期
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
